﻿using System;
using System.Linq;
using Ninject;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace HobSoft.SoccerBet2014.Domain.Implementation.Service
{
    using Domain.Core;
    using Domain.IRepositories;
    using Domain.Models;
    using Domain.Models.KeyHelper;
    using Domain.ClientService;

    public class DbAttribute : Attribute
    {
    }

    public class CacheAttribute : Attribute
    {

    }

    public class PersistentModelsService : IService
    {
        [Inject]
        [Db]
        protected IGameRepository DbGameRepository
        {
            get;
            set;
        }
        [Inject]
        [Cache]
        protected IGameRepository CacheGameRepository
        {
            get;
            set;
        }

        [Inject]
        [Db]
        protected IBFEventRepository DbBfEventRepository
        {
            get;
            set;
        }

        [Inject]
        [Cache]
        protected IBFEventRepository CacheBfEventRepository
        {
            get;
            set;

        }

        [Inject]
        [Db]
        protected IGameMappingRepository DbGameMappingRepository
        {
            get;
            set;
        }

        [Inject]
        [Cache]
        protected IGameMappingRepository CacheGameMappingRepository
        {
            get;
            set;
        }

        [Inject]
        [Cache]
        protected IBookmakerRepository CacheBookmakerRepository
        {
            get;
            set;
        }

        [Inject]
        [Db]
        protected IBookmakerRepository DbBookmakerRepository
        {
            get;
            set;
        }

        [Inject]
        [Cache]
        protected IBFMarketRepository CacheBFMarketRepository
        {
            get;
            set;
        }

        [Inject]
        [Db]
        protected IBFMarketRepository DbBFMarketRepository
        {
            get;
            set;
        }

        protected IBfRequestService BfRequestService
        {
            get;
            set;
        }

        public PersistentModelsService()
        {

        }

        public virtual void StoreEarlyGamesDb()
        {
            var games = CacheGameRepository.GetMany(g => g.State == Models.Game.GameState.PreGame);
            DbGameRepository.AddOrUpdate(games);
        }

        public virtual void StoreOddsDb()
        {

        }

        public virtual void StoreMarketDb()
        {

        }

        public virtual void StoreBfEventCache()
        {
            var mapping = DbGameMappingRepository.GetMany(DateTime.Now, DateTime.Now.AddHours(24));
            var evtIds = mapping.Select(m => m.EventID).ToArray();
            var bfEvents = DbBfEventRepository.GetMany(be => evtIds.Contains(be.EventID) && be.NotAvailable == false);
            var upevIds = bfEvents.Select(be => be.EventID).ToArray();
            var bfmarkets = DbBFMarketRepository.GetMany(m => upevIds.Contains(m.EventID));
            if (bfEvents.Any())
            {
                CacheBfEventRepository.AddOrUpdate(bfEvents);
                CacheBfEventRepository.Update(be => !upevIds.Contains(be.EventID), ube => new BFEvent { NotAvailable = true });
            }
            if (mapping.Any())
            {
                CacheGameMappingRepository.AddOrUpdate(mapping);
            }
            if (bfmarkets.Any())
            {
                CacheBFMarketRepository.AddOrUpdate(bfmarkets);
            }
        }

        public virtual void StoreBookmakerCache()
        {
            var bklist = DbBookmakerRepository.GetMany(b => b.Available);
            if (bklist.Any())
                CacheBookmakerRepository.AddOrUpdate(bklist);
        }

        public virtual void UpdateLiveBfEventCache()
        {
            StoreBfEventCache();
        }

        public virtual void StoreBfMarketCache()
        {

        }

        public virtual void CheckBfMarketClose()
        {
            var startTime = DateTime.Now.AddHours(-3);
            var beforeTime = DateTime.Now.AddHours(-1);

            var mapping = CacheGameMappingRepository.GetMany(startTime, beforeTime);
            if (!mapping.Any()) return;
            var gKeys = mapping.Select(m => KeyGenerateHelper.Create<Game>(m.BmID, m.GameID));
            var uniKeyGameRepository = CacheGameRepository as IUniKeyReadRepository<Game>;
            IList<Game> mappingGames = new List<Game>();
            if (uniKeyGameRepository != null)
                mappingGames = uniKeyGameRepository.GetMany(gKeys);
            else
                mappingGames = CacheGameRepository.GetMany(g => gKeys.Contains(g.Key));
            var liveGIds = mappingGames.Where(g => g.State != Game.GameState.Finish).Select(g => g.GameID);

            var bfIds = mapping.Where(m => liveGIds.Contains(m.GameID)).Select(m => m.EventID).ToArray();
            if (!bfIds.Any()) return;
            var markets = CacheBFMarketRepository.GetMany(m => bfIds.Contains(m.EventID) && m.CategoryID == 11);
            var mkIds = markets.Select(m => m.MarketID).ToArray();
            if (!mkIds.Any()) return;
            BfRequestService.HasLogin().ContinueWith(t =>
            {
                if (t.IsCompleted)
                {
                    if (t.Result)
                    {
                        BfRequestService.GetMarketBook(mkIds).ContinueWith(tmb =>
                        {
                            if (tmb.IsCompleted && tmb.Result != null)
                            {
                                foreach (var marketBook in tmb.Result)
                                {
                                    if (marketBook.Status == Models.BfRaw.MarketStatus.CLOSED)
                                    {
                                        var market = markets.FirstOrDefault(m => m.MarketID == marketBook.MarketId);
                                        if (market == null) continue;
                                        var mp = mapping.FirstOrDefault(m => m.EventID == market.EventID);
                                        if (mp == null) continue;
                                        CacheGameRepository.Finish(mp.BmID, mp.GameID);
                                    }
                                }
                            }
                        });
                    }
                }
            });
        }
    }
}
